﻿//   You should have received a copy of the GNU General Public License
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.

//   This program comes with ABSOLUTELY NO WARRANTY.

using System;
using System.Data;
using System.IO;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Drawing;
using System.Net;
using GoogleMaps;
/// <summary>
/// Summary description for cGoogleMap
/// </summary>
/// 
    public class GoogleObject
    {
        public GoogleObject()
        {
        }
        static int debugMode = 2;
        public static bool writeit(StreamWriter w, string content)
        {
            try
            {
                if (w != null)
                {
                    w.WriteLine("{0} - {1}", DateTime.Now.ToString("yyyyMMdd HH:mm:ss"), content);
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        public static bool debug(string logfile, string content)//default 1
        {
            return debug(1, logfile, content);
        }
        public static bool debug(int level, string logfile, string content)//default 1
        {
            if (debugMode < level)
            {
                return false;//abort writing 
            }
            try
            {
                StreamWriter w = File.AppendText(logfile);
                writeit(w, content);
                w.Close();
                w.Dispose();
            }
            catch (Exception ex)
            {
                return false;
            }
            return false;
        }
        public GoogleObject(GoogleObject prev)
        {
            Points = GooglePoints.CloneMe(prev.Points);
            Polylines = GooglePolylines.CloneMe(prev.Polylines);
            Polygons = GooglePolygons.CloneMe(prev.Polygons);
            ZoomLevel = prev.ZoomLevel;
            ShowZoomControl = prev.ShowZoomControl;
            ShowMapTypesControl = prev.ShowMapTypesControl;
            Width = prev.Width;
            Height = prev.Height;
            MapType = prev.MapType;
            APIKey = prev.APIKey;
            ShowTraffic = prev.ShowTraffic;
        }

        GooglePoints _gpoints = new GooglePoints();
        public GooglePoints Points
        {
            get { return _gpoints; }
            set { _gpoints = value; }
        }

        GooglePolylines _gpolylines = new GooglePolylines();
        public GooglePolylines Polylines
        {
            get { return _gpolylines; }
            set { _gpolylines = value; }
        }

        GooglePolygons _gpolygons = new GooglePolygons();
        public GooglePolygons Polygons
        {
            get { return _gpolygons; }
            set { _gpolygons = value; }
        }

        GooglePoint _centerpoint = new GooglePoint();
        public GooglePoint CenterPoint
        {
            get { return _centerpoint; }
            set { _centerpoint = value; }
        }

        int _zoomlevel = 3;
        public int ZoomLevel
        {
            get { return _zoomlevel; }
            set { _zoomlevel = value; }
        }
        // Convert ZoomLevel to ScaleMap
        public double ScaleMap(int levelzoom)
        {
            double zoom = 0;
            if(levelzoom==1) zoom=591657550.500000;
            else if(levelzoom==2) zoom=295828775.300000;
            else if(levelzoom==3) zoom=147914387.600000;
            else if(levelzoom==4) zoom=73957193.820000;
            else if(levelzoom==5) zoom=36978596.910000;
            else if(levelzoom==6) zoom=18489298.450000;
            else if(levelzoom==7) zoom=9244649.227000;
            else if(levelzoom==8) zoom=4622324.614000;
            else if(levelzoom==9) zoom=2311162.307000;
            else if(levelzoom==10) zoom=1155581.153000;
            else if(levelzoom==11) zoom=577790.576700;
            else if(levelzoom==12) zoom=288895.288400;
            else if(levelzoom==13) zoom=144447.644200;
            else if(levelzoom==14) zoom=72223.822090;
            else if(levelzoom==15) zoom=36111.911040;
            else if(levelzoom==16) zoom=18055.955520;
            else if(levelzoom==17) zoom=9027.977761;
            else if(levelzoom==18) zoom=4513.988880;
            else if(levelzoom==19) zoom=2256.994440;
            else if(levelzoom==20) zoom=1128.497220;
            else zoom = 36111.911040;
            return zoom;
        }
        bool _showzoomcontrol = true;
        public bool ShowZoomControl
        {
            get { return _showzoomcontrol; }
            set { _showzoomcontrol = value; }
        }

        bool _showtraffic = false;
        public bool ShowTraffic
        {
            get { return _showtraffic; }
            set { _showtraffic = value; }
        }

        bool _showmaptypescontrol = true;
        public bool ShowMapTypesControl
        {
            get { return _showmaptypescontrol; }
            set { _showmaptypescontrol = value; }
        }

        string _width = "1300px";
        public string Width
        {
            get
            {
                return _width;
            }
            set
            {
                _width = value;
            }
        }

        string _height = "500px";
        public string Height
        {
            get
            {
                return _height;
            }
            set
            {
                _height = value;
            }
        }


        string _maptype = "";
        public string MapType
        {
            get
            {
                return _maptype;
            }
            set
            {
                _maptype = value;
            }
        }

        string _apikey = "";
        public string APIKey
        {
            get
            {
                return _apikey;
            }
            set
            {
                _apikey = value;
            }
        }

        string _apiversion = "2";
        public string APIVersion
        {
            get
            {
                return _apiversion;
            }
            set
            {
                _apiversion = value;
            }
        }
        public static Stream DownloadResource(string url)
        {
            MemoryStream stream = null;

            try
            {
                WebClient client = new WebClient();
                client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
                byte[] data = client.DownloadData(url);
                if (data.Length == 0)
                {
                    return null;
                }
                stream = new MemoryStream(data);
                client.Dispose();
            }
            catch (WebException e)
            {
                debug(1, "C:\\inetpub\\wwwroot\\logerror.txt", e.Message);
                stream = null;
            }
            return stream;
        }
        public static DataTable DownloadXML(string url)
        {
            DataTable table = null;
            DataSet ds = new DataSet();
            try
            {
                Stream stream = DownloadResource(url);
                if (stream == null)
                {
                    return null;
                }
                ds.ReadXml(stream);
                table = new DataTable();
                table.Columns.Add("Location");
                table.Columns.Add("Longitude");
                table.Columns.Add("Latitude");
                int iRow = 0;
                foreach (DataRow dr in ds.Tables["result"].Rows)
                {
                    List<Object> objData = new List<Object>();
                    objData.Add(dr[1].ToString().Trim());
                    objData.Add(ds.Tables["location"].Rows[iRow][1].ToString().Trim());
                    objData.Add(ds.Tables["location"].Rows[iRow][0].ToString().Trim());
                    table.Rows.Add(objData.ToArray());
                    iRow++;
                }
                ds.Dispose();
                stream.Close();
                stream.Dispose();
            }
            catch(Exception ex)
            {
                table = null;
            }
            return table;
        }
        // Convert Address to Coordinate
        public DataTable AddressToLongitudeLatitude(string address)
        {
            DataTable table = null;
            // Get latitude-longitude for address
            string url = "http://maps.googleapis.com/maps/api/geocode/xml?address=";
            url += address;
            url += "&sensor=false";
            try
            {
                table = DownloadXML(url);
            }
            catch(Exception ex)
            {
                table = null;
            }
            return table;
        }

        // Convert Coordinate to Address
        public DataTable LongitudeLatitudeToAddress(double longitude, double latitude)
        {
            DataTable table = null;

            // Get addess for latitude-longitude
            string url = "http://maps.googleapis.com/maps/api/geocode/xml?latlng=";
            url += latitude.ToString().Trim();
            url += ",";
            url += longitude.ToString().Trim();
            url += "&sensor=false";
            try
            {
                table = DownloadXML(url);
            }
            catch (Exception ex)
            {
                table = null;
            }
            return table;            
        }
        // Convert Coordinate to Address
        public string LongitudeLatitudeToStringAddress(double longitude, double latitude)
        {
            DataTable table = null;
            string st = "";
            // Get addess for latitude-longitude
            string url = "http://maps.googleapis.com/maps/api/geocode/xml?latlng=";
            url += latitude.ToString().Trim();
            url += ",";
            url += longitude.ToString().Trim();
            url += "&sensor=false";
            try
            {
                table = DownloadXML(url);
                st = table.Rows[0]["Location"].ToString();
            }
            catch (Exception ex)
            {
                table = null;
                st = "";
            }
            return st;
            //table.Columns.Add("Location");
            //table.Columns.Add("Longitude");
            //table.Columns.Add("Latitude");
        }
        // Convert Latlong to Pixel
        public Point LatLongToPixel(double latitude, double longitude, double zoom)
        {
            Point point = new Point();
            double centerPoint = Math.Pow(2, zoom + 7);
            double totalPixels = 2 * centerPoint;
            double pixelsPerLngDegree = totalPixels / 360;
            double pixelsPerLngRadian = totalPixels / (2 * Math.PI);
            double siny = Math.Min(Math.Max(Math.Sin(latitude * (Math.PI / 180)), -0.9999), 0.9999);
            point = new Point((int)Math.Round(centerPoint + longitude * pixelsPerLngDegree), (int)Math.Round(centerPoint - 0.5 * Math.Log((1 + siny) / (1 - siny)) * pixelsPerLngRadian));

            return point;
        }
        // Convert Pixel to Coordinate
        public GooglePoint PixelToLatLong(int pixelX, int pixelY, double zoom)
        {
            GooglePoint Point;
            double centerPoint = Math.Pow(2, zoom + 7);
            double totalPixels = Convert.ToUInt16(Width);
            double pixelsPerLngDegree = totalPixels / 360;
            double pixelsPerLngRadian = totalPixels / (2 * Math.PI);

            double siny = Math.Min(Math.Max(Math.Sin(pixelX * (Math.PI / 180)), -0.9999), 0.9999);
            Point = new GooglePoint("1",centerPoint + pixelY * pixelsPerLngDegree, centerPoint - 0.5 * Math.Log((1 + siny) / (1 - siny)) * pixelsPerLngRadian);
            return Point;
        }
        // Calculator angle for Object
        public int setAngle(double lat1, double lon1, double lat2, double lon2)
        {
            double tan = 0;
            int st = 0;
            if (Math.Abs(lon2 - lon1) < 0.0001)
            {
                if (lat2 > lat1)
                    st = 0;
                else
                    st = 8;
            }
            else
            {
                if (Math.Abs(lat2 - lat1) < 0.0001)
                {
                    if (lon2 > lon1)
                        st = 4;
                    else
                        st = 12;
                }
                else
                    if (lon2 > lon1)
                    {
                        tan = Math.Atan((lat2 - lat1) / (lon2 - lon1)) * 180 / 3.14259;
                        if (tan < 0.0) tan = 90.0 - tan;
                        if (0.0 <= tan && tan < 11.0)
                            st = 0;
                        else if (11 <= tan && tan < 34.0)
                            st = 1;
                        else if (34.0 <= tan && tan < 57.0)
                            st = 2;
                        else if (57.0 <= tan && tan < 79.0)
                            st = 3;
                        else if (79.0 <= tan && tan < 102.0)
                            st = 4;
                        else if (102.0 <= tan && tan < 125.0)
                            st = 5;
                        else if (125.0 <= tan && tan < 147.0)
                            st = 6;
                        else if (147.0 <= tan && tan < 170.0)
                            st = 7;
                        else if (170.0 <= tan && tan < 180.0)
                            st = 8;
                    }
                    else
                    {
                        tan = Math.Atan((lat2 - lat1) / (lon2 - lon1)) * 180 / 3.14259;
                        tan = tan - 90.0;
                        if (-11.0 <= tan && tan < 0.0)
                            st = 0;
                        else if (-34.0 <= tan && tan < -11.0)
                            st = 15;
                        else if (-57.0 <= tan && tan < -34.0)
                            st = 14;
                        else if (-79.0 <= tan && tan < -57.0)
                            st = 13;
                        else if (-102.0 <= tan && tan < -79.0)
                            st = 12;
                        else if (-125.0 <= tan && tan < -102.0)
                            st = 11;
                        else if (-147.0 <= tan && tan < -125.0)
                            st = 10;
                        else if (-170.0 <= tan && tan < -147.0)
                            st = 9;
                        else if (-180.0 <= tan && tan < -170.0)
                            st = 8;
                    }
            }
            return st;
        }
        //calculate distance for linear distance
        public double latlong_to_distance_km(double lat1, double lon1, double lat2, double lon2)
        {
            double dlon = (lon2 - lon1) * Math.PI/180.0;
            double dlat = (lat2 - lat1) * Math.PI / 180.0;
            double a = Math.Pow(Math.Sin(dlat / 2.0), 2.0) + Math.Cos(lat1 * Math.PI / 180.0) * Math.Cos(lat2 * Math.PI / 180.0) * Math.Pow(Math.Sin(dlon / 2.0),2.0);
            double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            double d = 6371 * c;
            return d;
        }
        //calculate distance for mile distance
        public double latlong_to_distance_mile(double lat1, double lon1, double lat2, double lon2)
        {
            double dlon = (lon2 - lon1) * Math.PI / 180.0;
            double dlat = (lat2 - lat1) * Math.PI / 180.0;
            double a = Math.Pow(Math.Sin(dlat/2.0), 2) + Math.Cos(lat1*Math.PI/180.0) * Math.Cos(lat2*Math.PI/180.0) * Math.Pow(Math.Sin(dlon/2.0), 2);
            double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
            double d = 3956 * c;
            return d;
        }
        // Calculate center point from 2 coordinate point
        public PointF Midpoint(double lat1, double lon1, double lat2, double lon2)
        {            
            double dlon = (lon2 - lon1) * Math.PI / 180.0;
            double dlat = (lat2 - lat1) * Math.PI / 180.0;
            double Bx = Math.Cos(lat2) * Math.Cos(dlon);
            double By = Math.Cos(lat2) * Math.Sin(dlon);
            double lat3 = Math.Atan2(Math.Sin(lat1) + Math.Sin(lat2), Math.Sqrt((Math.Cos(lat1) + Bx) * (Math.Cos(lat1) + Bx) + By * By));
            double lon3 = lon1 + Math.Atan2(By, Math.Cos(lat1) + Bx);
            PointF mp = new PointF((float)lat3, (float)lon3);
            return mp;
        }
        // Convert deg to radian
        private double deg2rad(double deg)
        {
            return (deg * Math.PI / 180.0);
        }
        // Convert radian to deg
        private double rad2deg(double rad)
        {
            return (rad / Math.PI * 180.0);
        }
        // Get distance from Point1 to Point2
        private double GetDistance(double lat1, double lon1, double lat2, double lon2)
        {
            //code for Distance in Kilo Meter
            double theta = lon1 - lon2;
            double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
            dist = Math.Abs(Math.Round(rad2deg(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000, 0));
            return (dist);
        }
        // Get direction form point1 to point2
        private double GetDirection(double lat1, double lon1, double lat2, double lon2)
        {
            //code for Direction in Degrees
            double dlat = deg2rad(lat1) - deg2rad(lat2);
            double dlon = deg2rad(lon1) - deg2rad(lon2);
            double y = Math.Sin(dlon) * Math.Cos(lat2);
            double x = Math.Cos(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) - Math.Sin(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(dlon);
            double direct = Math.Round(rad2deg(Math.Atan2(y, x)), 0);
            if (direct < 0)
                direct = direct + 360;
            return (direct);
        }
        // Get speed from 
        private double GetSpeed(double lat1, double lon1, double lat2, double lon2, DateTime CurTime, DateTime PrevTime)
        {
            //code for speed in Kilo Meter/Hour
            TimeSpan TimeDifference = CurTime.Subtract(PrevTime);
            double TimeDifferenceInSeconds = Math.Round(TimeDifference.TotalSeconds, 0);
            double theta = lon1 - lon2;
            double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
            dist = rad2deg(Math.Acos(dist)) * 60 * 1.1515 * 1.609344;
            double Speed = Math.Abs(Math.Round((dist / Math.Abs(TimeDifferenceInSeconds)) * 60 * 60, 0));
            return (Speed);
        }
        // Get duration time from CurTime to prevTime
        private double GetDuration(DateTime CurTime, DateTime PrevTime)
        {
            //code for speed in Kilo Meter/Hour
            TimeSpan TimeDifference = CurTime.Subtract(PrevTime);
            double TimeDifferenceInSeconds = Math.Abs(Math.Round(TimeDifference.TotalSeconds, 0));
            return (TimeDifferenceInSeconds);
        }
        /* Returns the destination point from this point having travelled the given distance (in km)
         * @param   {Number} angle: Bearing in degrees from North
         * @param   {Number} R: Distance in km
         * @returns {LatLon} Destination point */
        // Calculate LatLong from distance
        public PointF distance_to_latlong(double lat, double lon, double angle, double R)
        {
            double d = R / 6371.0;  // d = angular distance covered on earth’s surface
            double lat1 = deg2rad(lat);
            double lon1 = deg2rad(lon);
            double Angle = deg2rad(angle);

            double dLat = d * Math.Cos(Angle);
            // nasty kludge to overcome ill-conditioned results around parallels of latitude:
            if (Math.Abs(dLat) < 1e-10) dLat = 0; // dLat < 1 mm
  
            double lat2 = lat1 + dLat;
            double dPhi = Math.Log(Math.Tan(lat2/2+Math.PI/4)/Math.Tan(lat1/2+Math.PI/4));
            double q;
            if (dLat / dPhi < 1000000)
                q = Math.Cos(lat1);
            else
                q = dLat / dPhi;
            double dLon = d * Math.Sin(Angle) / q;
  
            // check for some daft bugger going past the pole, normalise latitude if so
            if (Math.Abs(lat2) > Math.PI/2) lat2 = lat2>0 ? Math.PI-lat2 : -Math.PI-lat2;
  
            double lon2 = (lon1+dLon+3*Math.PI)%(2*Math.PI) - Math.PI;

            PointF mp = new PointF((float)rad2deg(lat2), (float)rad2deg(lon2));
            return mp;
        }
    }
    // Class Point on Map
    public class GooglePoint
    {
        public GooglePoint()
        {
        }

        string _pointstatus = ""; //N-New, D-Deleted, C-Changed, ''-No Action
        public string PointStatus
        {
            get { return _pointstatus; }
            set { _pointstatus = value; }
        }

        public GooglePoint(string pID, double plat, double plon, string picon, string pinfohtml)
        {
            ID = pID;
            Latitude = plat;
            Longitude = plon;
            IconImage = picon;
            InfoHTML = pinfohtml;
        }

        public GooglePoint(string pID, double plat, double plon, string picon)
        {
            ID = pID;
            Latitude = plat;
            Longitude = plon;
            IconImage = picon;
        }

        public GooglePoint(string pID, double plat, double plon)
        {
            ID = pID;
            Latitude = plat;
            Longitude = plon;
        }

        string _id = "";
        public string ID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }


        System.Drawing.Image _image;
        public System.Drawing.Image image
        {
            get { return _image; }
            set
            {
                //Get physical path of icon image. Necessary for Bitmap object.
                if (IconImage == "")
                    return;
                string ImageIconPhysicalPath = cCommon.GetLocalPath() + IconImage.Replace("/", "\\");
                //Find width and height of icon using Bitmap image.

                _image = System.Drawing.Image.FromFile(ImageIconPhysicalPath);
            }
        }

        string _icon = "";
        public string IconImage
        {
            get
            {
                return _icon;
            }
            set
            {
                //Get physical path of icon image. Necessary for Bitmap object.
                string sIconImage = value;
                if (sIconImage == "")
                    return;
                string ImageIconPhysicalPath = cCommon.GetLocalPath() + sIconImage.Replace("/", "\\");
                //Find width and height of icon using Bitmap image.

                using (System.Drawing.Image img = System.Drawing.Image.FromFile(ImageIconPhysicalPath))
                {
                    IconImageWidth = img.Width;
                    IconImageHeight = img.Height;
//                    _image = img;
                }
                _icon = cCommon.GetHttpURL() + sIconImage;
                _icon = value;
            }
        }

        double _angle = 0;
        public double angle
        {
            get
            {
                return _angle;
            }
            set
            {
                _angle = value;
            }
        }

        int _iconimagewidth = 24;
        public int IconImageWidth
        {
            get
            {
                return _iconimagewidth;
            }
            set
            {
                _iconimagewidth = value;
            }
        }

        int _iconimageheight = 24;
        public int IconImageHeight
        {
            get
            {
                return _iconimageheight;
            }
            set
            {
                _iconimageheight = value;
            }
        }

        double _lat = 0.0;
        public double Latitude
        {
            get
            {
                return _lat;
            }
            set
            {
                _lat = value;
            }
        }

        double _lon = 0.0;
        public double Longitude
        {
            get
            {
                return _lon;
            }
            set
            {
                _lon = value;
            }
        }

        string _infohtml = "";
        public string InfoHTML
        {
            get
            {
                return _infohtml;
            }
            set
            {
                _infohtml = value;
            }
        }
        //string _tooltiphtml = "";
        //public string TooltipHTML
        //{
        //    get
        //    {
        //        return _tooltiphtml;
        //    }
        //    set
        //    {
        //        _tooltiphtml = value;
        //    }
        //}
        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }

            // If parameter cannot be cast to Point return false.
            GooglePoint p = obj as GooglePoint;
            if ((System.Object)p == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (InfoHTML == p.InfoHTML) && (IconImage == p.IconImage) && (p.ID == ID) && (p.Latitude == Latitude) && (p.Longitude == Longitude);
        }
    }

    public class GooglePoints : CollectionBase
    {

        public GooglePoints()
        {
        }

        public static GooglePoints CloneMe(GooglePoints prev)
        {
            GooglePoints p = new GooglePoints();
            for (int i = 0; i < prev.Count; i++)
            {
                p.Add(new GooglePoint(prev[i].ID, prev[i].Latitude, prev[i].Longitude, prev[i].IconImage, prev[i].InfoHTML));
            }
            return p;
        }


        public GooglePoint this[int pIndex]
        {
            get
            {
                return (GooglePoint)this.List[pIndex];
            }
            set
            {
                this.List[pIndex] = value;
            }
        }

        public GooglePoint this[string pID]
        {
            get
            {
                for (int i = 0; i < Count; i++)
                {
                    if (this[i].ID == pID)
                    {
                        return (GooglePoint)this.List[i];
                    }
                }
                return null;
            }
            set
            {
                for (int i = 0; i < Count; i++)
                {
                    if (this[i].ID == pID)
                    {
                        this.List[i] = value;
                    }
                }
            }

        }

        public void Add(GooglePoint pPoint)
        {
            this.List.Add(pPoint);
        }
        public void Remove(int pIndex)
        {
            this.RemoveAt(pIndex);
        }
        public void Remove(string pID)
        {
            for (int i = 0; i < Count; i++)
            {
                if (this[i].ID == pID)
                {
                    this.List.RemoveAt(i);
                    return;
                }
            }
        }

        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }

            // If parameter cannot be cast to Point return false.
            GooglePoints p = obj as GooglePoints;
            if ((System.Object)p == null)
            {
                return false;
            }

            if (p.Count != Count)
                return false;


            for (int i = 0; i < p.Count; i++)
            {
                if (!this[i].Equals(p[i]))
                    return false;
            }
            // Return true if the fields match:
            return true;
        }
    }

    public class GooglePolyline
    {
        string _linestatus = ""; //N-New, D-Deleted, C-Changed, ''-No Action
        public string LineStatus
        {
            get { return _linestatus; }
            set { _linestatus = value; }
        }

        string _id = "";
        public string ID
        {
            get { return _id; }
            set { _id = value; }
        }

        GooglePoints _gpoints = new GooglePoints();
        public GooglePoints Points
        {
            get { return _gpoints; }
            set { _gpoints = value; }
        }

        string _colorcode = "#66FF00";
        public string ColorCode
        {
            get { return _colorcode; }
            set { _colorcode = value; }
        }

        int _width = 10;
        public int Width
        {
            get { return _width; }
            set { _width = value; }
        }

        bool _geodesic = false;
        public bool Geodesic
        {
            get { return _geodesic; }
            set { _geodesic = value; }
        }

        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }

            // If parameter cannot be cast to Point return false.
            GooglePolyline p = obj as GooglePolyline;
            if ((System.Object)p == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (Geodesic == p.Geodesic) && (Width == p.Width) && (p.ID == ID) && (p.ColorCode == ColorCode) && (p.Points.Equals(Points));
        }

    }

    public class GooglePolylines : CollectionBase
    {

        public GooglePolylines()
        {
        }

        public static GooglePolylines CloneMe(GooglePolylines prev)
        {
            GooglePolylines p = new GooglePolylines();
            for (int i = 0; i < prev.Count; i++)
            {
                GooglePolyline GPL = new GooglePolyline();
                GPL.ColorCode = prev[i].ColorCode;
                GPL.Geodesic = prev[i].Geodesic;
                GPL.ID = prev[i].ID;
                GPL.Points = GooglePoints.CloneMe(prev[i].Points);
                GPL.Width = prev[i].Width;
                p.Add(GPL);
            }
            return p;
        }

        public GooglePolyline this[int pIndex]
        {
            get
            {
                return (GooglePolyline)this.List[pIndex];
            }
            set
            {
                this.List[pIndex] = value;
            }
        }

        public GooglePolyline this[string pID]
        {
            get
            {
                for (int i = 0; i < Count; i++)
                {
                    if (this[i].ID == pID)
                    {
                        return (GooglePolyline)this.List[i];
                    }
                }
                return null;
            }
            set
            {
                for (int i = 0; i < Count; i++)
                {
                    if (this[i].ID == pID)
                    {
                        this.List[i] = value;
                    }
                }
            }
        }

        public void Add(GooglePolyline pPolyline)
        {
            this.List.Add(pPolyline);
        }
        public void Remove(int pIndex)
        {
            this.RemoveAt(pIndex);
        }
        public void Remove(string pID)
        {
            for (int i = 0; i < Count; i++)
            {
                if (this[i].ID == pID)
                {
                    this.List.RemoveAt(i);
                    return;
                }
            }
        }

    }


    public sealed class GoogleMapType
    {
        public const string NORMAL_MAP = "G_NORMAL_MAP";
        public const string SATELLITE_MAP = "G_SATELLITE_MAP";
        public const string HYBRID_MAP = "G_HYBRID_MAP";
        public const string TERRAIN_MAP = "G_TERRAIN_MAP";
    }

    public class cCommon
    {
        public cCommon()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        public static Random random = new Random();

        public static string GetHttpURL()
        {
            string[] s = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.Split(new char[] { '/' });
            string path = s[0] + "/";
            for (int i = 1; i < s.Length - 1; i++)
            {
                path = path + s[i] + "/";
            }
            return path;
        }

        public static string GetLocalPath()
        {
            string[] s = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.Split(new char[] { '/' });
            string PageName = s[s.Length - 1];
            s = System.Web.HttpContext.Current.Request.MapPath(PageName).Split(new char[] { '\\' });
            string path = s[0] + "\\";
            for (int i = 1; i < s.Length - 1; i++)
            {
                path = path + s[i] + "\\";
            }
            return path;
        }

        public static decimal RandomNumber(decimal min, decimal max)
        {
            decimal Fractions = 10000000;
            int iMin = (int)GetIntegerPart(min * Fractions);
            int iMax = (int)GetIntegerPart(max * Fractions);
            int iRand = random.Next(iMin, iMax);

            decimal dRand = (decimal)iRand;
            dRand = dRand / Fractions;

            return dRand;
        }


        public static decimal GetFractional(decimal source)
        {
            return source % 1.0m;
        }

        public static decimal GetIntegerPart(decimal source)
        {
            return decimal.Parse(source.ToString("#.00"));
        }

    }

    public class GooglePolygon
    {
        string _status = ""; //N-New, D-Deleted, C-Changed, ''-No Action
        public string Status
        {
            get { return _status; }
            set { _status = value; }
        }

        string _id = "";
        public string ID
        {
            get { return _id; }
            set { _id = value; }
        }

        GooglePoints _gpoints = new GooglePoints();
        public GooglePoints Points
        {
            get { return _gpoints; }
            set { _gpoints = value; }
        }

        string _strokecolor = "#0000FF";
        public string StrokeColor
        {
            get { return _strokecolor; }
            set { _strokecolor = value; }
        }

        string _fillcolor = "#66FF00";
        public string FillColor
        {
            get { return _fillcolor; }
            set { _fillcolor = value; }
        }

        int _strokeweight = 10;
        public int StrokeWeight
        {
            get { return _strokeweight; }
            set { _strokeweight = value; }
        }

        double _strokeopacity = 1;
        public double StrokeOpacity
        {
            get { return _strokeopacity; }
            set { _strokeopacity = value; }
        }

        double _fillopacity = 0.2;
        public double FillOpacity
        {
            get { return _fillopacity; }
            set { _fillopacity = value; }
        }

        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }

            // If parameter cannot be cast to Point return false.
            GooglePolygon p = obj as GooglePolygon;
            if ((System.Object)p == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (FillColor == p.FillColor) && (FillOpacity == p.FillOpacity) && (p.ID == ID) && (p.Status == Status) && (p.StrokeColor == StrokeColor) && (p.StrokeOpacity == StrokeOpacity) && (p.StrokeWeight == StrokeWeight) && (p.Points.Equals(Points));
        }

    }

    public class GooglePolygons : CollectionBase
    {

        public GooglePolygons()
        {
        }

        public static GooglePolygons CloneMe(GooglePolygons prev)
        {
            GooglePolygons p = new GooglePolygons();
            for (int i = 0; i < prev.Count; i++)
            {
                GooglePolygon GPL = new GooglePolygon();
                GPL.FillColor = prev[i].FillColor;
                GPL.FillOpacity = prev[i].FillOpacity;
                GPL.ID = prev[i].ID;
                GPL.Status = prev[i].Status;
                GPL.StrokeColor = prev[i].StrokeColor;
                GPL.StrokeOpacity = prev[i].StrokeOpacity;
                GPL.StrokeWeight = prev[i].StrokeWeight;
                GPL.Points = GooglePoints.CloneMe(prev[i].Points);
                p.Add(GPL);
            }
            return p;
        }

        public GooglePolygon this[int pIndex]
        {
            get
            {
                return (GooglePolygon)this.List[pIndex];
            }
            set
            {
                this.List[pIndex] = value;
            }
        }

        public GooglePolygon this[string pID]
        {
            get
            {
                for (int i = 0; i < Count; i++)
                {
                    if (this[i].ID == pID)
                    {
                        return (GooglePolygon)this.List[i];
                    }
                }
                return null;
            }
            set
            {
                for (int i = 0; i < Count; i++)
                {
                    if (this[i].ID == pID)
                    {
                        this.List[i] = value;
                    }
                }
            }
        }

        public void Add(GooglePolygon pPolygon)
        {
            this.List.Add(pPolygon);
        }
        public void Remove(int pIndex)
        {
            this.RemoveAt(pIndex);
        }
        public void Remove(string pID)
        {
            for (int i = 0; i < Count; i++)
            {
                if (this[i].ID == pID)
                {
                    this.List.RemoveAt(i);
                    return;
                }
            }
        }

    }
